﻿using facebook.businuss.netcore.sdk.Model;
using facebook.businuss.netcore.sdk.Sdk.IService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace facebook.businuss.netcore.sdk.Sdk
{
    public class APIRequest
    {
        public static readonly string USER_AGENT = APIConfig.USER_AGENT;

        private static IRequestExecutor executor = new DefaultRequestExecutor();

        protected APIContext context;
        protected bool useVideoEndpoint = false;
        protected String nodeId;
        protected String endpoint;
        protected String method;
        protected List<String> paramNames;
        protected Dictionary<String, Object> Param = new Dictionary<string, object>();
        protected List<string> returnFields;
        private String overrideUrl;
        //private APIResponse lastResponse = null;

       

        public APIRequest(APIContext context, String nodeId, String endpoint, String method, List<String> paramNames)
        {
            this.context = context;
            this.nodeId = nodeId;
            this.endpoint = endpoint;
            this.method = method;
            this.paramNames = paramNames;
        }

        public  void setParam(string param, object value)
        {
            Param[param] = value;
        }

        public static void setParam(string filtering, List<object> filterringValue)
        {
        }

        //public APIResponse parseResponse(String response, String header)
        //{
        //    if (parser != null) {
        //        return parser.parseResponse(response, context, this, header);
        //    } else {
        //        return APINode.parseResponse(response, context, new APIRequest<APINode>(context, nodeId, endpoint, method, paramNames), header);
        //    }
        //}


        public ResponseWrapper execute(Dictionary<String, Object> extraParams)
        {
            // extraParams are one-time params for this call,
            // so that the APIRequest can be reused later on.
            ResponseWrapper response = null;
            try
            {
                response = executor.execute(method, getApiUrl(), getAllParams(extraParams), context);
            }
            catch (Exception e)
            {
                throw;
            }
            return response;
        }

        public ResponseWrapper execute(string url)
        {
            // extraParams are one-time params for this call,
            // so that the APIRequest can be reused later on.
            ResponseWrapper response = null;
            try
            {
                response = executor.execute(method, url, null, context);
            }
            catch (Exception e)
            {
                throw;
            }
            return response;
        }

        private String getApiUrl()
        {
            if (overrideUrl != null)
            {
                return overrideUrl;
            }
            String endpointBas = useVideoEndpoint ? context.getVideoEndpointBase() : context.getEndpointBase();
            return endpointBas + "/" + context.getVersion() + "/" + nodeId + endpoint;
        }

        private Dictionary<String, Object> getAllParams(Dictionary<String, Object> extraParams)
        {
            if (overrideUrl != null)
            {
                return new Dictionary<String, Object>();
            }
            Dictionary<String, Object> allParams = new Dictionary<String, Object>(Param);
            if (extraParams != null)
            {
                foreach (var kv in extraParams)
                {
                    allParams.TryAdd(kv.Key,kv.Value);
                }
            }
            allParams.TryAdd("access_token", context.getAccessToken());
     
            if (returnFields != null) allParams.Add("fields", string.Join(',',returnFields));

            return allParams;
        }

        public APIRequestGetInsights getInsights(String nodeId, APIContext context)
        {
            return  new APIRequestGetInsights(nodeId,context);
        }


        protected void requestFieldInternal(String field, bool addField)
        {
            if (returnFields == null) returnFields = new List<string>();
            if (addField)
            {
                if (!returnFields.Contains(field)) returnFields.Add(field);
            }
            else
            {
                returnFields.Remove(field);
            }
        }
    } 
}
